package com.zrkizzy.module.scheduler.utils;

import com.zrkizzy.common.models.dto.system.scheduler.SchedulerJobDTO;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

/**
 * 任务执行工具类
 *
 * @author zhangrongkang
 * @since 2024/3/2
 */
@Slf4j
public class SchedulerJobInvokeUtil {

    /**
     * 执行定时任务
     *
     * @param schedulerJobDTO 定时任务数据传输对象
     */
    public static void invokeMethod(SchedulerJobDTO schedulerJobDTO) throws Exception {
        // 获取调用目标字符串
        String invokeTarget = schedulerJobDTO.getInvokeTarget();

        // 拆分出类名称和调用方法
        String classInfo = SchedulerJobBuildUtil.getTargetClassInfo(invokeTarget);
        String methodName = SchedulerJobBuildUtil.getTargetMethodName(invokeTarget);
        List<Object[]> params = SchedulerJobBuildUtil.getTargetMethodParams(invokeTarget);

        // 反射对应的Bean或类
        Object targetClass = SchedulerJobBuildUtil.reflexTargetClass(classInfo);
        // 执行定时任务方法
        invokeMethod(targetClass, methodName, params);
    }

    /**
     * 调用定时任务方法
     *
     * @param targetClass 调用类
     * @param methodName 方法名称
     * @param params 方法参数
     */
    private static void invokeMethod(Object targetClass, String methodName, List<Object[]> params) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 如果参数对象不为空
        if (Objects.nonNull(params) && !params.isEmpty()) {
            // 反射对应方法
            Method method = targetClass.getClass().getMethod(methodName, SchedulerJobBuildUtil.getMethodParamsType(params));
            // 调用方法
            method.invoke(targetClass, SchedulerJobBuildUtil.getMethodParamsValue(params));
        } else {
            // 无参方法则直接反射方法并调用
            Method method = targetClass.getClass().getMethod(methodName);
            method.invoke(targetClass);
        }
    }

}
